Add relation planner extension support #17843
Open
+2,483
−8
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Which issue does this PR close?
Rationale for this change
DataFusion currently lacks a clean way to customize how SQL table factors (FROM clause elements) are planned into logical plans. The proposed workaround in #17633 has a critical limitation: it only works at the query root level and cannot handle custom relations inside JOINs, CTEs, or subqueries.
This PR introduces a
RelationPlannerextension API that allows users to intercept and customize table factor planning at any nesting level, enabling support for SQL syntax extensions that go beyond simple table-valued functions. For example, you can now combine multiple custom relation types in a single query:Why not use
TableFunctionImpl? The existingTableFunctionImpltrait is perfect for simple table-valued functions (likegenerate_series(1, 10)), but it cannot handle:TABLESAMPLEthat modifies an existing table reference)MATCH_RECOGNIZE,PIVOT,UNPIVOT)RelationPlannerfills this gap by intercepting arbitraryTableFactorAST nodes and transforming them into logical plans.What changes are included in this PR?
Core API (feat commit):
RelationPlannertrait for customizing SQL table factor planningRelationPlannerContexttrait providing SQL utilities to extension plannersSessionContext::register_relation_planner()for registering custom plannersSessionStateintegration with priority-based planner chainSqlToRelto invoke planners at all nesting levels (not just root)Tests (test commit):
datafusion/core/tests/user_defined/relation_planner.rsExamples (example commit):
table_sample.rs- SQL TABLESAMPLE clause support (BERNOULLI/SYSTEM methods, REPEATABLE seed), adapted from feat: Add example for implementingSAMPLEusing extension APIs #17633.match_recognize.rs- SQL MATCH_RECOGNIZE pattern matching on event streamspivot_unpivot.rs- SQL PIVOT/UNPIVOT transformations for data reshapingNote: The examples are intentionally verbose to demonstrate the full design and capabilities of the API. They should be simplified and streamlined before merging (reduce duplication, extract common patterns, improve documentation structure).
Are these changes tested?
Yes:
TableFunctionImplAre there any user-facing changes?
Yes, this is a new public API:
New APIs:
datafusion_expr::planner::RelationPlannertraitdatafusion_expr::planner::RelationPlannerContexttraitdatafusion_expr::planner::PlannedRelationstructdatafusion_expr::planner::RelationPlanningenumSessionContext::register_relation_planner()SessionState::register_relation_planner()andrelation_planners()SessionStateBuilder::with_relation_planners()ContextProvider::get_relation_planners()This is an additive change that extends existing extensibility APIs (
ExprPlanner,TypePlanner) and requires thesqlfeature flag.AI-Generated Code Disclosure
This PR was developed with significant assistance from
claude-sonnet-4.5. The AI was heavily involved in all parts of the process, from initial design to actual code to writing the PR description, which greatly sped up the process. All its output was however carefully reviewed before submitting.